import * as utils from "../modules/utils.js";
import { basemaps } from "../modules/basemap.js";
import {
  themetypes,
  colorpats,
  chartypes,
  areas,
  layerlevels,
  propthemes,
  themeobj,
  thememetas,
} from "../modules/mapmetas.js";
import {
  fill,
  fill_upd,
  outline,
  outline_upd,
  flow,
  flow_upd,
  label,
  label_upd,
  chart,
  scatter,
  scatter_upd,
  symbol,
  heat,
  heat_upd,
  iso,
  sde,
  grid,
  grid_upd,
  geodatas,
  defaulgradient,
} from "../modules/maptheme.js";
import "../lib/turf.min.js";
import "../lib/mapbox-gl2.6.1.js";
import "../lib/mapbox-gl-language.js";
import "../lib/jquery-3.6.0.min.js";
import "../lib/vue.js";
import "../lib/element-ui.js";
import "../lib/html2canvas.min.js";
import "../lib/echarts.min.js";
import "../lib/chroma.min.js";
import "../lib/d3.v5.min.js";
import "../lib/data-set.min.js";

let mlancontrol = new MapboxLanguage({
  defaultLanguage: "zh-Hans",
});
// eslint-disable-next-line no-unused-vars
var app = new Vue({
  el: "#app",
  data: {
    message: "Hello Vue!",
    legends: [],
    visiblemaker: false,
    map: null,
    thememap: { name: "", option: { layers: [] } },
    themetypes,
    thememetas,
    propthemes,
    colorpats,
    chartypes,
    areas,
    basemaps,
    layerlevels,
    fieldsdict: [],
    loading: false,
    markers: [],
    themeupdatefuncs: {
      fill: fill_upd,
      outline: outline_upd,
      flow: flow_upd,
      label: label_upd,
      scatter: scatter_upd,
      heat: heat_upd,
      grid: grid_upd,
    },
    lastbasemap: "",
  },
  methods: {
    gridcalc(layer,idx,theme,idxtheme) {
      let that = this;
      let layerid = theme.type + idxtheme + "-" + layer.level + idx;
      let squareGrid = geodatas[layerid];
      let source = that.map.getSource(`src-${layerid}`);
      let ftidx = 0;
      let end = false;
      function getsquare() {
        let ft = squareGrid.features[ftidx];
        utils
          .nodeapi("spatialSummary", {
            level: "cun",
            fields: theme.field,
            geo: Terraformer.WKT.convert(ft.geometry),
          })
          .then((res) => {
            ft.properties[theme.field] = res[theme.field] * 1;
            source.setData(squareGrid);
            ftidx++;
            if (ftidx >= squareGrid.features.length) {
              if (!end) {
                let vals = squareGrid.features.map(
                  (f) => f.properties[theme.field] * 1
                );
                theme.minmax = { min: d3.min(vals), max: d3.max(vals) };
                let colorrender = [
                  "interpolate",
                  ["linear"],
                  ["get", theme.field],
                  theme.minmax.min,
                  defaulgradient[0],
                  theme.minmax.max,
                  defaulgradient[1],
                ];
                that.map.setPaintProperty(layerid, "fill-color", colorrender);
                if (!that.map.getLayer('label'+layerid)) {
                  that.map.addLayer({
                    id: 'label'+layerid,
                    type: "symbol",
                    source: source.id, // reference the data source
                    layout: {
                      "text-field":`{${theme.field}}`
                    },
                  });
                }
                end = true;
              }
              return;
            } else getsquare(ftidx);
          });
      }
      for (let i = 0; i < (theme.threadcount || 20); i++) {
        getsquare();
      }
    },
    legenditemstyle(legend, item) {
      let css = `opacity: 1;display: inline-block;background-color:${
        item.color
      };${
        legend.type == "scatter"
          ? `width:${item.size}px;height:${item.size}px;border-radius:50%;`
          : "width: 15px;height: 15px;"
      }`;
      return css;
    },
    addcolor(colorgradient) {
      colorgradient.push(chroma.random().hex());
    },
    deltheme(layer, idx) {
      layer.themes.splice(idx, 1);
    },
    addtheme(layer) {
      themeobj.type = "";
      layer.themes.unshift(JSON.parse(JSON.stringify(themeobj)));
    },
    dellayer(idx) {
      this.thememap.option.layers.splice(idx, 1);
    },
    addlayer() {
      this.thememap.option.layers.unshift({
        level: "shi",
        area: "",
        themes: [],
      });
    },
    async createmap(onload) {
      if (!onload) {
        this.map.setStyle(
          basemaps[this.thememap.option.basemap].value || "tdtVec"
        );
        this.addLanControl();
        this.lastbasemap = this.thememap.option.basemap;
      }
      //清除legends
      this.legends = [];
      //清除marker
      this.markers.forEach((mk) => mk.remove());
      this.markers.splice(0, this.markers.length - 1);

      this.createlayers();
    },
    uptheme(idx, idxtheme) {
      if (idxtheme == 0) {
        return;
      }
      utils.swap(
        this.thememap.option.layers[idx].themes,
        idxtheme,
        idxtheme - 1
      );
    },
    downtheme(idx, idxtheme) {
      if (idxtheme == this.thememap.option.layers[idx].themes.length - 1) {
        return;
      }
      utils.swap(
        this.thememap.option.layers[idx].themes,
        idxtheme,
        idxtheme + 1
      );
    },
    uplayer(idx) {
      if (idx == 0) {
        return;
      }
      utils.swap(this.thememap.option.layers, idx, idx - 1);
    },
    downlayer(idx) {
      if (idx == this.thememap.option.layers.length - 1) {
        return;
      }
      utils.swap(this.thememap.option.layers, idx, idx + 1);
    },
    hidetheme(idx, idxtheme) {
      $("#panel" + idx + "-" + idxtheme).toggle();
    },
    hidepanel(idx) {
      $("#panel" + idx).toggle();
    },
    async savethememap() {
      let that = this;
      //保存截图
      $("#maker").hide();
      //新增保存设置为非模板，删除id
      let url;
      if (that.thememap.id != null) {
        url = `http://${ipapi}/thememaps`;
      } else {
        url = `http://${ipapi}/thememaps/add`;
      }

      //保存配置
      $.ajax({
        type: "POST",
        url,
        contentType: "application/json; charset=utf-8",
        data: JSON.stringify(this.thememap),
        success: function (res) {
          //模板和地图编辑不更新id，模板另存更新id
          if (that.thememap.id == null) {
            that.thememap.id = res.id;
          }
          var filename = `thememap_${that.thememap.id}.png`;
          utils.savepic("main", filename, false, that);
          that.$message("保存成功");
        },
      });
    },
    updatalayerdata: async function (layer) {
      let filter = utils.getfilter(layer.area);
      let that = this;
      let fieldset = new Set();
      for (let theme of layer.themes) {
        if (theme.field) {
          fieldset.add(theme.field);
        }
        if (theme.fields) {
          theme.fields.forEach((f) => {
            fieldset.add(f);
          });
        }
      }
      let fields =
        [...fieldset].length > 0
          ? `${[...fieldset].join(",")},area,codename,code`
          : "area,codename,code";
      //加载面数据源
      let geodata;
      if (
        layer.themes.map((t) => t.type).includes("fill") ||
        layer.themes.map((t) => t.type).includes("outline") ||
        layer.themes.map((t) => t.type).includes("flow") ||
        layer.themes.map((t) => t.type).includes("grid")
      ) {
        geodata = await utils.geodata(layer.level, fields, filter);
        geodatas[layer.level] = geodata;
        if (!that.map.getSource(`src-${layer.level}`)) {
          that.map.addSource(`src-${layer.level}`, {
            type: "geojson",
            data: turf.featureCollection([]),
            // promoteId:'code'
            generateId: true,
          });
        }
        let sourcearea = that.map.getSource(`src-${layer.level}`);
        geodata && sourcearea.setData(geodata);
      }
      //加载点数据源
      let geopt = await utils.geodata(layer.level + "_pt", fields, filter);
      geodatas[layer.level + "-pt"] = geopt;
      let srcpt = `src-${layer.level}-pt`;
      if (!that.map.getSource(srcpt)) {
        that.map.addSource(srcpt, {
          type: "geojson",
          data: turf.featureCollection([]),
          generateId: true,
        });
      }
      let sourcept = that.map.getSource(srcpt);
      sourcept.setData(geopt);
      return { geodata, geopt };
    },
    createLayer: async function (layer, idx) {
      let data = await this.updatalayerdata(layer);
      let themefuncs = {
        fill,
        outline,
        flow,
        label,
        chart,
        scatter,
        symbol,
        heat,
        iso,
        sde,
        grid,
      };
      for (let [tid, theme] of layer.themes.entries()) {
        let par = {
          theme,
          layer,
          geodata: data.geodata,
          map: this.map,
          app: this,
          layerid: theme.type + tid + "-" + layer.level + idx,
        };
        if (["scatter", "chart", "symbol", "iso"].includes(theme.type)) {
          par.geodata = data.geopt;
        }
        await themefuncs[theme.type](par);
      }
    },
    addLanControl() {
      if (
        this.thememap.option.basemap?.indexOf("mapbox") == 0 ||
        !this.thememap.option.basemap
        // && !this.map.hasControl(mlancontrol)
      ) {
        try {
          this.map.removeControl(mlancontrol);
        } catch (e) {
          console.log(e);
        }
        this.map.addControl(mlancontrol);
      }
    },
    createlayers: async function () {
      for (let [idx, layer] of this.thememap.option.layers.entries()) {
        await this.createLayer(layer, idx).catch((err) => console.log(err));
      }
    },
    updatetheme(layer, idx, theme, idxtheme) {
      this.themeupdatefuncs[theme.type] &&
        this.themeupdatefuncs[theme.type]({
          map: this.map,
          layerid: theme.type + idxtheme + "-" + layer.level + idx,
          theme,
          app,
          layer,
        });
    },
    updatelayers() {
      for (let [idx, layer] of this.thememap.option.layers.entries()) {
        for (let [tid, theme] of layer.themes.entries()) {
          this.updatetheme(layer, idx, theme, tid);
        }
      }
    },
  },
  watch: {
    thememap: function () {},
  },
  mounted: async function () {
    /** 初始化数据 */
    let that = this;
    let optionid = utils.getQueryVariable("id");
    let thememap;
    if (optionid) {
      thememap = await $.get(`http://${ipapi}/thememaps/${optionid}`);
    } else {
      thememap = { name: "空模板", option: { basemap: "tdtVec", layers: [] } };
    }

    thememap.option.layers.forEach((layer) => {
      layer.themes.forEach((theme) => {
        if (!theme.colorgradient || theme.colorgradient.length == 0)
          theme.colorgradient = defaulgradient;
        if (!theme.color) theme.color = "#000000";
        //消除以往的图例配置
        if (!theme.legend || typeof theme.legend == "boolean")
          theme.legend = { show: true };
      });
    });
    console.log(thememap);

    this.thememap = thememap;
    /** 初始化模板编辑状态 */
    let edittemplate = utils.getQueryVariable("edittemplate");
    if (this.thememap.template == "1" && !edittemplate) {
      this.thememap.template = "0";
      this.thememap.id = null;
    }
    mapboxgl.accessToken =
      "pk.eyJ1IjoiaG91eGlleXUiLCJhIjoiY2pldjE5amU3NndzeDM5bzd5bm9ncDgycyJ9.j1F-Lgid3L5k2Abm8_xTeQ";

    this.fieldsdict = await $.getJSON(`http://${ipapi}/dictSummary`);
    this.lastbasemap = this.thememap.option["basemap"];
    const map = new mapboxgl.Map({
      container: "map",
      style: basemaps[this.thememap.option["basemap"] || "tdtVec"].value,
      center: [117.974103, 36.374436],
      zoom: 7,
      preserveDrawingBuffer: true,
    });
    this.map = map;
    this.addLanControl();
    map.on("load", function () {
      map.resize();
      var svgXML = `<svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg"> <path d="M529.6128 512L239.9232 222.4128 384.7168 77.5168 819.2 512 384.7168 946.4832 239.9232 801.5872z" p-id="9085" fill="#ffffff"></path> </svg> `;
      var svgBase64 = `data:image/svg+xml;base64,${window.btoa(
        unescape(encodeURIComponent(svgXML))
      )}`;
      let arrowIcon = new Image(20, 20);
      arrowIcon.src = svgBase64;
      arrowIcon.onload = function () {
        map.addImage("arrowIcon", arrowIcon);
      };
      that.createmap(true);
    });
  },
});
